{
 "metadata": {
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  },
  "orig_nbformat": 2,
  "kernelspec": {
   "name": "python3",
   "display_name": "Python 3.7.4 64-bit ('base': conda)"
  },
  "interpreter": {
   "hash": "2a7e95a32014fc1ccf24626d45a98c6e7b4373277259c22f47a91d487fc3e8a5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2,
 "cells": [
  {
   "source": [
    "## 数据可视化 Matplotlib\n",
    "## [官方文档](https://matplotlib.org/stable/tutorials/introductory/sample_plots.html)  \n",
    "* Matplotlib.pyplot子库可绘制各类**2D**可视化图形(快捷方式,每种可视化效果为一种类)  \n",
    "* 选取恰当的图形展示数据的含义:找到数据对应的最佳显示方式\n",
    "* Matplotlib.seaborn子库可绘制更高颜值的图\n",
    "* 在Web浏览器创建动态的,交互式图像可用[Plotly](https://github.com/plotly/plotly.py)或者Bokeh"
   ],
   "cell_type": "markdown",
   "metadata": {}
  },
  {
   "source": [
    "### pyplot 基本操作\n",
    "import matplotlib.pyplot as plt    # 一种约定\n",
    "import numpy as np\n",
    "plt.figure(figsize=(4,3),dpi=100)\n",
    "plt.plot([0,2,4,6,8],[3,1,5,4,8],'ro',abs(2*np.random.randn(10)),'g--',label='idn')  # 两组数据\n",
    "# 一维数据默认为Y轴,X轴为数据的索引\n",
    "plt.ylabel('grade')\n",
    "plt.axis([-1,10,0,6])   # 横轴范围(-1,10),纵轴范围(0,6)\n",
    "plt.legend(loc='best')    # 放置图例\n",
    "# plt.savefig(r'C:/Users/ZSY/Pictures/Camera Roll/test',dpi=600) # 存储为PNG文件\n",
    "\n",
    "plt.show()"
   ],
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "### plt.plot()函数\n",
    "# 绘制多条曲线时,各曲线的X不能省略\n",
    "# plt.plot(x,y,format_string,**kwargs)\n",
    "# 主要控制format_string,由格式字符串决定曲线颜色,线形,标记,还有很多参数可用于图形精细控制\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt \n",
    "\n",
    "a = np.arange(10)\n",
    "plt.plot(a,a*1.5,'r',a,a*3.5,':',a,a*5.5,'rx')  # 各颜色,线形,标记字符串可叠加组合使用\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# DataFrame等pd数据有.plot的绘图方法,可以不用plt.()的函数\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    " \n",
    "data = pd.DataFrame(np.random.rand(10,4).cumsum(0),columns=list('ABCD'),index=np.arange(0,100,10))      # 自动为每一列绘制折线\n",
    "print(data)\n",
    "data.plot()     # 即.plot.line()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt \n",
    "plt.plot?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "### plt的中文显示,并不自带,需要代码辅助\n",
    "import matplotlib.pyplot as plt    # 一种约定\n",
    "# import matplotlib\n",
    "\n",
    "# # --- # 方法一,改变全局字体\n",
    "# matplotlib.rcParams['font.family'] = 'SimHei'   # 中文字体,黑体,将改变图中的所有字体(包括数字)\n",
    "# matplotlib.rcParams['font.style'] = 'normal'  # 常规\n",
    "# matplotlib.rcParams['font.size'] = 10   # 字号\n",
    "# plt.plot([0,2,4,6,8],[3,1,5,4,8])\n",
    "# plt.ylabel('纵坐标')\n",
    "# plt.xlabel('横坐标')\n",
    "# plt.show()\n",
    "# # --- #\n",
    "\n",
    "# --- # 方法二,改变局部字体\n",
    "plt.plot([0,2,4,6,8],[3,1,5,4,8])\n",
    "plt.ylabel('纵坐标',fontproperties='Kaiti',fontsize=15)\n",
    "plt.xlabel('横坐标',fontproperties='LiSu',fontsize=15)\n",
    "plt.show()\n",
    "# --- #\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "### plt的文本显示\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "plt.plot([0,2,4,6,8],[3,1,5,4,8])\n",
    "\n",
    "plt.ylabel('纵坐标',fontproperties='Kaiti',fontsize=15,color='green')\n",
    "plt.xlabel('横坐标',fontproperties='Kaiti',fontsize=15)\n",
    "# --- # 标题\\文本\\注释\n",
    "plt.title('正弦波实例',fontproperties='SimHei')\n",
    "plt.text(4,2,r'$\\mu=100$',fontsize=25)  # 在(4,2)坐标位置引入LaTex文本\n",
    "plt.annotate('拐点',fontproperties='Kaiti',fontsize=15,\n",
    "                xy=(4,5),xytext=(2,7),     # 箭头所指位置与注释所在位置\n",
    "                arrowprops=dict(facecolor='red',shrink=0.05,width=1))  # 箭头属性,shrink为间距\n",
    "# --- #\n",
    "plt.grid(True)  # 网格使能\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "### 分区绘图plt.subplot() jupyter中须将所有的绘图命令放在单个的notebook单元格中\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt \n",
    "\n",
    "def f(t):\n",
    "    return np.exp(-t)*np.cos(2*np.pi*t) # np.pi即为3.1415\n",
    "\n",
    "a = np.arange(0.0,5.0,0.02)\n",
    "\n",
    "plt.subplot(211)    # 创建一个(2,1)的绘图区,选取第1个进行绘制\n",
    "plt.plot(a,f(a),'k')    # 在当前活动的或最近创建的AxesSubplot上操作\n",
    "\n",
    "                    # 使用plt.subplot()只能一个一个的添加\n",
    "plt.subplot(2,2,4)  # 创建一个(2,2)的绘图区,选取第4个进行绘制\n",
    "plt.plot(a,np.cos(2*np.pi*a),'r--')\n",
    "\n",
    "plt.subplot(223).set_xticks([1,50,100])     # 设置x轴坐标\n",
    "plt.plot(np.random.randn(100).cumsum())     # 随机漫步\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用plt.subplots()可一次性添加\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    " \n",
    "fig, axes = plt.subplots(2, 2) # 先创建一个2×2的绘图区\n",
    "data = pd.Series(10*np.random.rand(16), index=list('abcdefghijklmnop'))\n",
    "data.plot.bar(ax=axes[1,1], color='b', alpha = 0.5)  # 选取第4个进行绘制\n",
    "plt.subplots_adjust(wspace=0,hspace=0)      # 各图之间间距为0\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "### plt复杂的子绘图区域 plt.subplot2grid() 和 gridspec()\n",
    "import matplotlib.pyplot as plt \n",
    "import matplotlib.gridspec as gridspec\n",
    "\n",
    "# --- # 方法一 plt.subplot2grid()\n",
    "plt.subplot2grid((3,3),(0,0),colspan=3)    # 创建3×3的网格,选择(0,0)点,延伸3列\n",
    "plt.text(0.5,0.5,'N0.1')\n",
    "\n",
    "plt.subplot2grid((3,3),(1,0),colspan=2)\n",
    "plt.text(0.5,0.5,'N0.2')\n",
    "\n",
    "plt.subplot2grid((3,3),(1,2),rowspan=2)     # 创建3×3的网格,选择(1,2)点,延伸2行\n",
    "plt.text(0.5,0.5,'N0.3')\n",
    "\n",
    "plt.subplot2grid((3,3),(2,0))\n",
    "plt.text(0.5,0.5,'N0.4')\n",
    "\n",
    "plt.subplot2grid((3,3),(2,1))\n",
    "plt.text(0.5,0.5,'N0.5')\n",
    "plt.show()\n",
    "# --- # \n",
    "\n",
    "# --- # 方法二 GridSpec()\n",
    "gs = gridspec.GridSpec(3,3)     # 创建3×3的网格\n",
    "\n",
    "n1 = plt.subplot(gs[0,:])       # 用gs[]定位,配合subplot绘制子图\n",
    "plt.text(0.5,0.5,'N0.1')\n",
    "\n",
    "n2 = plt.subplot(gs[1,:-1])\n",
    "plt.text(0.5,0.5,'N0.2')\n",
    "\n",
    "n3 = plt.subplot(gs[1:,-1])\n",
    "plt.text(0.5,0.5,'N0.3')\n",
    "\n",
    "n4 = plt.subplot(gs[2,0])\n",
    "plt.text(0.5,0.5,'N0.4')\n",
    "\n",
    "n5 = plt.subplot(gs[2,1])\n",
    "plt.text(0.5,0.5,'N0.5')\n",
    "plt.show()\n",
    "# --- # "
   ]
  },
  {
   "source": [
    ">* 坐标图: plt.plot()\n",
    ">* 柱状图：plt.boxplot()展示多个分类的数据变化和同类别各变量之间的比较情况。  \n",
    ">* 条形图：plt.bar()类似柱状图，只不过两根轴对调了一下。  \n",
    ">* 折线图：plt.展示数据随时间或有序类别的波动情况的趋势变化。 \n",
    ">* 极坐标图: plt.polar() 角度空间的数据展示\n",
    ">* 柱线图：结合柱状图和折线图在同一个图表展现数据。  \n",
    ">* 散点图：plt.scatter()用于发现各变量之间的关系。  \n",
    ">* 饼图：plt.pie() 用来展示各类别占比，比如男女比例。  \n",
    ">* 热力图：以特殊高亮的形式显示访客热衷的页面区域和访客所在的地理区域的图示。  \n",
    ">* 词云：展现文本信息，对出现频率较高的“关键词”予以视觉上的突出,比如用户画像的标签。\n",
    ">* 功率谱密度图：plt.psd() \n",
    ">* 谱图：plt.specgram()\n",
    ">* X-Y相关性函数: plt.cohere()\n",
    ">* 步阶图：plt.step()\n",
    ">* 直方图：plt.hist() 展现数据在最小到最大值之间出现的频率\n",
    ">* 等值图：plt.contour()\n",
    ">* 垂直图：plt.vlines()\n",
    ">* 柴火图：plt.stem()\n",
    ">* 数据日期：plt.plot_date()\n",
    ">* ..."
   ],
   "cell_type": "markdown",
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "### 绘图函数\n",
    "# 饼图：plt.pie() 的绘制 占比\n",
    "import matplotlib.pyplot as plt \n",
    "\n",
    "labels = 'Frogs','Hogs','Dogs','Logs'   # 各部分标签\n",
    "sizes = [15,30,45,10]   # 各部分大小\n",
    "explode = (0,0.1,0,0)   # 突出的部分及距离\n",
    "\n",
    "plt.pie(sizes,explode=explode,labels=labels,autopct='%1.1f%%',  # 百分比显示方式\n",
    "        shadow=True,startangle=90)\n",
    "plt.axis('equal')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 直方图：plt.hist() 的绘制\n",
    "import numpy as np \n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "np.random.seed(0)   # 保留随机出现的数组\n",
    "mu ,sigma = 100, 20\n",
    "a = np.random.normal(mu,sigma,size=100)\n",
    "print(a)\n",
    "\n",
    "plt.hist(a,bins=20,histtype='bar',facecolor='b',alpha=1)   \n",
    " # 分别对应 \"数组\",\"切分步长的大小\",显示形式,颜色,透明度\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 堆积柱状图\n",
    "import pandas as pd\n",
    "import numpy as np \n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "df = pd.DataFrame(np.random.rand(6, 4),\n",
    "\t\t\t\tindex=['one', 'two', 'three', 'four', 'five', 'six'],\n",
    "\t\t\t\t# 用pd.index() 创建索引，并赋给 columns 作为列标签\n",
    "\t\t\t\tcolumns=pd.Index(['A', 'B', 'C', 'D'], name='Genus'))\n",
    "print(df)\n",
    "df.plot.barh(stacked=True, alpha=0.5)      # 将heng的bar堆叠起来,更凸显比例\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 极坐标图: 不用plt.polar() \n",
    "# 使用面向对象的方法绘制图像\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "N = 20            # 生成的数据个数\n",
    "theta = np.linspace(0.0,2*np.pi,N,endpoint=False)   # 生成N个(0,2Π)的数据\n",
    "radii = 10*np.random.rand(N)    # 生成N个(0,10)的随机数\n",
    "width = np.pi / 4 * np.random.rand(N)\n",
    "\n",
    "ax = plt.subplot(111,projection='polar')    # 将subplot()变为对象\n",
    "# plt.show()            # 生成极坐标空白模板\n",
    "bars = ax.bar(theta,radii,width=width,bottom=0.0)\n",
    "# plt.show()              # 各角度数据填充\n",
    "\n",
    "for r,bar in zip(radii,bars):     # 改变各bar的颜色\n",
    "    bar.set_facecolor(plt.cm.viridis(r / 10.))\n",
    "    bar.set_alpha(0.5)      \n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 散点图：不用plt.scatter()\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "fig , ax = plt.subplots()# 等价于fig, ax1 = plt.subplots(1, 1);fig对应图表,ax对象区域\n",
    "ax.plot(10*np.random.randn(100),10*np.random.randn(100),'o')\n",
    "ax.set_title('Simple Scatter')\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "### 引力波绘制\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from scipy.io import wavfile    # 波形读取库\n",
    "\n",
    "rate_h, hstrain= wavfile.read(r\"H1_Strain.wav\",\"rb\")\n",
    "rate_l, lstrain= wavfile.read(r\"L1_Strain.wav\",\"rb\")\n",
    "#reftime, ref_H1 = np.genfromtxt('GW150914_4_NR_waveform_template.txt').transpose()\n",
    "reftime, ref_H1 = np.genfromtxt('wf_template.txt').transpose() #使用python123.io下载文件\n",
    "\n",
    "htime_interval = 1/rate_h\n",
    "ltime_interval = 1/rate_l\n",
    "fig = plt.figure(figsize=(12, 6))\n",
    "\n",
    "# 丢失信号起始点\n",
    "htime_len = hstrain.shape[0]/rate_h\n",
    "htime = np.arange(-htime_len/2, htime_len/2 , htime_interval)\n",
    "plth = fig.add_subplot(221)\n",
    "plth.plot(htime, hstrain, 'y')\n",
    "plth.set_xlabel('Time (seconds)')\n",
    "plth.set_ylabel('H1 Strain')\n",
    "plth.set_title('H1 Strain')\n",
    "\n",
    "ltime_len = lstrain.shape[0]/rate_l\n",
    "ltime = np.arange(-ltime_len/2, ltime_len/2 , ltime_interval)\n",
    "pltl = fig.add_subplot(222)\n",
    "pltl.plot(ltime, lstrain, 'g')\n",
    "pltl.set_xlabel('Time (seconds)')\n",
    "pltl.set_ylabel('L1 Strain')\n",
    "pltl.set_title('L1 Strain')\n",
    "\n",
    "pltref = fig.add_subplot(212)\n",
    "pltref.plot(reftime, ref_H1)\n",
    "pltref.set_xlabel('Time (seconds)')\n",
    "pltref.set_ylabel('Template Strain')\n",
    "pltref.set_title('Template')\n",
    "fig.tight_layout()\n",
    "\n",
    "plt.savefig(\"Gravitational_Waves_Original.png\")\n",
    "plt.show()\n",
    "plt.close(fig)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "###  seaborn绘图:简化了很多常用可视化类型的生成\n",
    "import seaborn as sns\n",
    "macro = pd.read_csv('macrodata.csv')\n",
    "data = macro[['cpi', 'm1', 'tbilrate', 'unemp']]\n",
    "trans_data = np.log(data).diff().dropna()\n",
    "\n",
    "# 两组数之间的关系\n",
    "sns.regplot('m1', 'unemp', data=trans_data)\n",
    "plt.title('Changes in log %s versus log %s' % ('m1', 'unemp'))\n",
    "\n",
    "# 散点图矩阵:非对角线上为每两个变量的散点图，对角线上为每个变量的直方图或密度估计\n",
    "sns.pairplot(trans_data, diag_kind='kde', plot_kws={'alpha': 0.2})  \n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ]
}